package com.juqi.fileclear;

import com.drew.imaging.jpeg.JpegMetadataReader;
import com.drew.imaging.mp4.Mp4MetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifSubIFDDirectory;
import com.drew.metadata.mp4.media.Mp4MetaDirectory;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;

public class Main {

    public static void main(String[] args) {
        if (args == null || args.length == 0) {
           System.out.println("---------------------参数错误--------------------");
            return;
        }
        String targetPath = args[0];

        File file = new File(targetPath);
        if (!file.exists() || file.isFile()) {
            return;
        }
       System.out.println("--------------------------开始监控目录：" + targetPath + "--------------------------");
        Path path = Paths.get(targetPath);
        try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
            //给path路径加上文件观察服务
            path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
            while (true) {
                final WatchKey key = watchService.take();

                for (WatchEvent<?> watchEvent : key.pollEvents()) {

                    final WatchEvent.Kind<?> kind = watchEvent.kind();

                    if (kind == StandardWatchEventKinds.OVERFLOW) {
                        continue;
                    }
                    //创建事件
                    if (kind == StandardWatchEventKinds.ENTRY_CREATE) {
                        Path filePath = (Path) watchEvent.context();
                        File f = new File(targetPath + "/" + filePath);
                        if (!f.exists()||f.isDirectory()) {
                            continue;
                        }
                        //检查文件是否写入完成，开始执行整理
                        if (checkFileWritingOn(f)) {
                            clear(targetPath, f);
                        }
                    }
                }
                // 重设WatchKey
                boolean valid = key.reset();
                // 如果重设失败，退出监听
                if (!valid) {
                    break;
                }
            }

        } catch (IOException | InterruptedException ex) {
            System.err.println(ex);
        }

    }

    /**
     * 整理单个文件到指定目录下
     *
     * @param targetPath 存放根目录
     * @param f          文件
     */
    public static void clear(String targetPath, File f) {
        if (targetPath == null || !new File(targetPath).exists() || !f.exists() || f.isDirectory()) {
            return;
        }

        Date picDate = readCreateTime(f);
        if (picDate == null) {
            return;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(picDate);
        String descPath = targetPath + "/" + calendar.get(Calendar.YEAR) + String.format("%02d", (calendar.get(Calendar.MONTH) + 1));
        File descFile = new File(descPath);
        if (!descFile.exists()) {
            descFile.mkdir();
        }
        while (true) {
            File newFile=new File(descPath + "/" + f.getName());
            f.renameTo(newFile);
            if (f.exists()) {
                if (newFile.exists()) {
                    f.delete();
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                continue;
            }
            break;
        }

       System.out.println("--------------------------文件被复制到" + descPath + "/" + f.getName() + "--------------------------");
    }

    /**
     * 获取拍摄日期
     *
     * @param file 文件
     * @return 拍摄日期
     */
    private static Date readCreateTime(File file) {

        Metadata metadata = null;
        try {
            if (file.getName().endsWith("mp4") || file.getName().endsWith("MP4")) {
                metadata = Mp4MetadataReader.readMetadata(file);
            } else if (file.getName().endsWith("jpg") || file.getName().endsWith("JPG")) {
                metadata = JpegMetadataReader.readMetadata(file);
            } else {
                return null;
            }

            if (metadata == null || metadata.getDirectories() == null) {
                return null;
            }
            Iterator<Directory> it = metadata.getDirectories().iterator();

            while (it.hasNext()) {
                Directory directory = it.next();
                String dateStr =null;
                if (file.getName().endsWith("mp4") || file.getName().endsWith("MP4")) {
                    dateStr = directory.getString(Mp4MetaDirectory.TAG_CREATION_TIME);
                   System.out.println("拍摄时间: " + dateStr);
                    if (dateStr != null) {
                        SimpleDateFormat df = new SimpleDateFormat("EEE MMM dd HH:mm:ss 'CST' yyyy",Locale.US);
                        return df.parse(dateStr);
                    }
                } else if (file.getName().endsWith("jpg") || file.getName().endsWith("JPG")) {
                    dateStr = directory.getString(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL);
                   System.out.println("拍照时间: " + dateStr);
                    if (dateStr != null) {
                        DateFormat df = new SimpleDateFormat("yyyy:MM:dd");
                        return df.parse(dateStr);
                    }
                } else {
                   continue;
                }

            }
        } catch (FileNotFoundException e) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
            Date date = readCreateTime(file);
            if (date != null) {
                return date;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 判断文件是否被写入
     * @param file
     * @return
     * @throws Exception
     */
    public static boolean checkFileWritingOn(File file){
        long oldLen = 0;
        long newLen = 0;
        while(true){
            newLen = file.length();
            if (newLen==0||(newLen - oldLen) > 0) {
                oldLen = newLen;
               System.out.println(file.length());
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
               System.out.println("文件写入完成："+file.getName());
                return true;
            }
        }
    }

}
